package be.dch.gui;

import java.awt.EventQueue;
import java.io.PrintStream;

import org.apache.log4j.Appender;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import be.dch.gui.panels.OutputPanel;
import be.dch.util.Log4jOutputStream;
import be.dch.util.Log4jTextAreaAppender;

/**
 * Launch the application.
 * 
 * 
 * Perform tasks in this order : log basic system information promptly, show a
 * splash screen upon startup show the main screen remove the splash screen once
 * the main screen is shown
 * 
 * These tasks are performed in a thread-safe manner.
 * 
 * @author EH053
 */
public final class Launcher {

    private static SplashScreen fSplashScreen;
    private static GarminMapGuiWindow mapGui;
    private static final Logger LOG = Logger.getLogger(Launcher.class);
    private static final String SPLASH_IMAGE = "/images/openstreetmap.png";

    private Launcher() {
	// Launcher class no cosntructor needed.
    }

    /**
     * Launch the application and display the main window.
     * 
     * @param aArgs
     *            are ignored by this application, and may take any value.
     */
    public static void main(final String... aArgs) {
	Launcher.initLogger();
	Launcher.showSplashScreen();
	Launcher.configureApplication();
	EventQueue.invokeLater(new SplashScreenCloser());
    }

    /**
     * Show a simple graphical splash screen.
     */
    private static void showSplashScreen() {
	Launcher.LOG.info("Showing the splash screen.");
	Launcher.fSplashScreen = new SplashScreen(Launcher.SPLASH_IMAGE);
	Launcher.fSplashScreen.splash();
    }

    /**
     * Display the main window of the application to the user.
     */
    private static void configureApplication() {

	Launcher.LOG.debug("Configuring application...");
	Launcher.redirectSystemStreams();
	Launcher.mapGui = GarminMapGuiWindow.getInstance();

	// TODO remove thread.sleep
	try {
	    Thread.sleep(999L);
	} catch (final InterruptedException e) {
	    Launcher.LOG.error(e.getMessage());
	}

    }

    private static void initLogger() {
	final Appender logAppender = new Log4jTextAreaAppender(new PatternLayout("%d{dd-MM-yyyy | HH:mm:ss} | %-5p | %m%n"), OutputPanel.getInstance().getTxtArea());
	logAppender.setName("stdout");
	Logger.getRootLogger().addAppender(logAppender);
	final Appender consoleAppender = new ConsoleAppender(new PatternLayout("%d{dd-MM-yyyy | HH:mm:ss} | %-5p | %m%n | %C{1}"));
	consoleAppender.setName("console");
	Logger.getRootLogger().addAppender(consoleAppender);
	Logger.getRootLogger().setLevel(Level.DEBUG);
    }

    /**
     * Removes the splash screen.
     */
    private static final class SplashScreenCloser implements Runnable {
	public void run() {
	    Launcher.mapGui.setVisible(true);
	    Launcher.LOG.debug("Closing the splash screen.");
	    Launcher.fSplashScreen.dispose();
	}
    }

    private static void redirectSystemStreams() {
	System.setOut(new PrintStream(new Log4jOutputStream(Level.INFO), true));
	System.setErr(new PrintStream(new Log4jOutputStream(Level.ERROR), true));
    }

}
